package com.roads.engineering.service.impl;

import com.roads.common.config.MasterConfig;
import com.roads.common.constant.Constants;
import com.roads.common.constant.UserConstants;
import com.roads.common.core.domain.entity.SysUser;
import com.roads.common.utils.DateUtils;
import com.roads.common.utils.SecurityUtils;
import com.roads.common.utils.StringUtils;
import com.roads.common.utils.file.FileUtils;
import com.roads.common.utils.uuid.IdUtils;
import com.roads.engineering.domain.ChangeOrderDetail;
import com.roads.engineering.domain.ChangeOrderMaster;
import com.roads.engineering.mapper.ChangeOrderDetailMapper;
import com.roads.engineering.mapper.ChangeOrderMasterMapper;
import com.roads.engineering.service.IChangeOrderMasterService;
import com.roads.project.domain.ProBoqMeterage;
import com.roads.project.domain.ProCompany;
import com.roads.project.domain.ProInstitution;
import com.roads.project.domain.ProProject;
import com.roads.project.mapper.ProBoqMeterageMapper;
import com.roads.project.mapper.ProCompanyMapper;
import com.roads.project.mapper.ProInstitutionMapper;
import com.roads.project.mapper.ProProjectMapper;
import com.roads.project.service.IProBoqMeterageService;
import com.roads.system.mapper.SysAnnexFileMapper;
import com.roads.system.mapper.SysUserMapper;
import com.roads.system.service.ISysMessageService;
import com.roads.workflow.domain.WorkflowMeterageNode;
import com.roads.workflow.domain.WorkflowTaskDelivery;
import com.roads.workflow.mapper.WorkflowMeterageNodeMapper;
import com.roads.workflow.service.IWorkflowTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 变更令申报Service业务层处理
 * 
 * @author nhp
 * @date 2022-01-07
 */
@Service
public class ChangeOrderMasterServiceImpl implements IChangeOrderMasterService {

    @Autowired
    private ChangeOrderMasterMapper mapper;

    @Autowired
    private ChangeOrderDetailMapper detailMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ProInstitutionMapper institutionMapper;

    @Autowired
    private ProProjectMapper projectMapper;

    @Autowired
    private ProCompanyMapper companyMapper;

    @Autowired
    private IWorkflowTaskService workflowTaskService;

    @Autowired
    private ISysMessageService messageService;

    @Autowired
    private ProBoqMeterageMapper meterageMapper;

    @Autowired
    private SysAnnexFileMapper sysAnnexFileMapper;

    @Autowired
    private WorkflowMeterageNodeMapper workflowMeterageNodeMapper;

    @Autowired
    private IProBoqMeterageService boqMeterageService;

    /**
     * 根据主键ID查询详情
     * 
     * @param id 变更令申报主键
     * @return 变更令申报
     */
    @Override
    public ChangeOrderMaster getModelById(Long id) {
        return mapper.getModelById(id);
    }

    /**
     * 查询列表
     * 
     * @param model 变更令申报
     * @return 变更令申报
     */
    @Override
    public List<ChangeOrderMaster> selectModelList(ChangeOrderMaster model) {
        return mapper.selectModelList(model);
    }

    /**
     * 校验变更令好是否唯一
     *
     * @param model 变更令申报
     * @return 结果
     */
    @Override
    public String checkChangeOrderNoUnique(ChangeOrderMaster model) {
        Long changeId = StringUtils.isNull(model.getChangeId()) ? -1L : model.getChangeId();
        ChangeOrderMaster search = mapper.checkChangeOrderNoUnique(model.getChangeOrderNo());
        if (StringUtils.isNotNull(search) && !search.getChangeId().equals(changeId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 新增
     * 
     * @param model 变更令申报
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(ChangeOrderMaster model) {
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 获取流程实例
        WorkflowMeterageNode workflowMeterageNode = workflowMeterageNodeMapper.getModelByBeginNodeAndUser(loginUser.getUserName(), Constants.WORKFLOW_TYPE_ENGINEERING);
        // 任务uuid
        String uuid = IdUtils.simpleUuid();
        // 设置 标段名称，项目名称，单位名称
        ProInstitution bid = institutionMapper.getModelByInnerCode(model.getInstitutionCode());
        model.setInstitutionName(bid.getInstitutionName());
        ProProject project = projectMapper.selectProProjectByProjectId(bid.getProjectId());
        model.setProjectId(project.getProjectId());
        model.setProjectName(project.getProjectName());
        ProCompany company = companyMapper.selectProCompanyByCompanyId(bid.getCompanyId());
        model.setCompanyName(company.getCompanyName());
        // 设置当前部门和用户名称
        model.setCurrentDept(loginUser.getDeptId());
        model.setCurrentDeptName(loginUser.getDept().getDeptName());
        model.setCurrentUser(loginUser.getUserName());
        model.setCurrentUserName(loginUser.getNickName());
        model.setCreateBy(loginUser.getUserName());
        model.setCreateTime(DateUtils.getNowDate());
        model.setUuid(uuid);
        model.setWorkflowUuid(workflowMeterageNode.getWorkflowUuid());
        mapper.insert(model);
        // 创建流程
        workflowTaskService.createTask(uuid, Constants.WORKFLOW_TYPE_ENGINEERING, Constants.MENU_TYPE_CHANGE, loginUser, workflowMeterageNode);
        return 1;
    }

    /**
     * 修改
     * 
     * @param model 变更令申报
     * @return 结果
     */
    @Override
    public int update(ChangeOrderMaster model) {
        model.setUpdateTime(DateUtils.getNowDate());
        return mapper.update(model);
    }

    /**
     * 批量删除
     * 
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            // 查找主表信息
            ChangeOrderMaster master = mapper.getModelById(ids[i]);
            String uuid = master.getUuid();
            // 删除主表信息
            mapper.delete(ids[i]);
            // 删除细表信息
            detailMapper.deleteByChangeId(ids[i]);
            // 删除流程
            workflowTaskService.deleteTask(uuid);
            // 删除消息
            messageService.deleteByUuid(uuid);
            // 删除附件
            sysAnnexFileMapper.deleteByUuid(uuid);
            String filePath = MasterConfig.getUploadAnnexPath() + "/" + Constants.MENU_TYPE_CHANGE + "/" + uuid;
            FileUtils.deleteDirectory(new File(filePath));
        }
        return 1;
    }

    /**
     * 删除
     * 
     * @param id 变更令申报主键
     * @return 结果
     */
    @Override
    public int delete(Long id) {
        return mapper.delete(id);
    }

    /**
     * 传送
     *
     * @param delivery 传送对象
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int delivery(WorkflowTaskDelivery delivery) {
        // 当前登录用户
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 主表处理 修改当前部门和当前用户
        ChangeOrderMaster master = mapper.getModelByUuid(delivery.getTaskUuid());
        // 传送至哪个用户，非当前登录用户
        SysUser deliveryUser = userMapper.selectUserByUserName(delivery.getUser());
        master.setCurrentDept(deliveryUser.getDeptId());
        master.setCurrentDeptName(deliveryUser.getDept().getDeptName());
        master.setCurrentUser(deliveryUser.getUserName());
        master.setCurrentUserName(deliveryUser.getNickName());
        mapper.update(master);
        // 细表处理 将当前登录用户数据复制给传送至用户，如果传送至用户里面包含数据，则先删除
        ChangeOrderDetail search = new ChangeOrderDetail();
        search.setChangeId(master.getChangeId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailMapper.deleteByUser(master.getChangeId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        List<ChangeOrderDetail> details = detailMapper.selectModelList(search);
        for (ChangeOrderDetail detail : details) {
            detail.setDept(deliveryUser.getDeptId());
            detail.setDeptName(deliveryUser.getDept().getDeptName());
            detail.setUser(deliveryUser.getUserName());
            detail.setUserName(deliveryUser.getNickName());
        }
        // 批量插入
        if (details.size() > 0) {
            detailMapper.insertBatch(details);
        }
        // 流程处理
        workflowTaskService.deliveryTask(delivery, loginUser, deliveryUser);
        // 消息处理
        messageService.handleDeliveryMessage(master.getUuid(), loginUser.getUserName());
        messageService.createDeliveryMessage(
                master.getUuid(),
                deliveryUser.getUserName(),
                "/engineering/change",
                "由" + loginUser.getNickName() + "传送的变更令申报",
                loginUser.getUserName());
        return 1;
    }

    /**
     * 批量锁定
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int lock(Long[] ids) {
        long startTime = System.currentTimeMillis();
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 循环处理锁定数据
        for (int i = 0; i < ids.length; i++) {
            long changeId = ids[i];
            // 主表状态处理
            ChangeOrderMaster master = mapper.getModelById(changeId);
            master.setStatus(Constants.LOCK);
            mapper.update(master);
            // 完成流程处理
            workflowTaskService.finishTask(master.getUuid(), loginUser);
            // 消息处理
            messageService.handleDeliveryMessage(master.getUuid(), loginUser.getUserName());
            // 生成变更计量清单
            ChangeOrderDetail searchDetail = new ChangeOrderDetail();
            searchDetail.setChangeId(changeId);
            searchDetail.setUser(master.getCurrentUser());
            List<ChangeOrderDetail> details = detailMapper.selectModelList(searchDetail);
            genChangeMeterageBoq(details, master);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("锁定变更令耗时：" + (endTime - startTime) + " ms");
        return 1;
    }

    /**
     * 解锁
     *
     * @param master 主表
     * @param id 主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int unlock(ChangeOrderMaster master, Long id) {
        master.setStatus(Constants.UNLOCK);
        mapper.update(master);
        // 删除流程完成信息
        workflowTaskService.deleteFinishTask(master.getUuid());
        // 当前数据所在位置的消息改正未读状态
        messageService.updateMessageStatusByUnread(master.getUuid(), master.getCurrentUser());
        // 删除该变更令下已生成的变更计量清单
        boqMeterageService.deleteChangeBoqByChangeOrderNo(master.getChangeOrderNo());
        return 1;
    }

    /**
     * 生成变更计量清单
     *
     * @param details 变更计量清单集合
     * @param master 变更令主表信息
     */
    private void genChangeMeterageBoq(List<ChangeOrderDetail> details, ChangeOrderMaster master) {
        // 变更计量清单
        List<ProBoqMeterage> changeMeterageList = new ArrayList<>();
        // 存放最大序列号map
        Map<String, Integer> serialNumberMap = new HashMap<>();
        for (ChangeOrderDetail detail : details) {
            // 原来的计量清单
            ProBoqMeterage meterage = meterageMapper.getModelByMeterageBoqCode(detail.getMeterageBoqCode());
            // 标段清单编号
            String institutionBoqCode = meterage.getInstitutionBoqCode();
            // 需要新增的变更计量清单
            ProBoqMeterage insertMeterage = new ProBoqMeterage();
            // 初始化变更计量清单
            insertMeterage.setMeterageBoqType("1");
            // 序列号
            Integer maxSerialNumber = serialNumberMap.get(institutionBoqCode);
            if (StringUtils.isNull(maxSerialNumber)) {
                maxSerialNumber = meterageMapper.getMaxSerialNumber(institutionBoqCode);
            }
            maxSerialNumber++;
            serialNumberMap.put(institutionBoqCode, maxSerialNumber);
            insertMeterage.setSerialNumber(maxSerialNumber);
            insertMeterage.setMeterageBoqCode(institutionBoqCode + Constants.BOQ_SEPARATOR + maxSerialNumber);
            insertMeterage.setInstitutionCode(meterage.getInstitutionCode());
            insertMeterage.setInstitutionBoqCode(meterage.getInstitutionBoqCode());
            insertMeterage.setBoqCode(detail.getBoqCode());
            insertMeterage.setBoqName(detail.getBoqName());
            insertMeterage.setAncestors(detail.getAncestors());
            insertMeterage.setOrderNum(detail.getOrderNum());
            insertMeterage.setUnit(detail.getUnit());
            insertMeterage.setPrice(detail.getPrice());
            insertMeterage.setAmount(detail.getAmount());
            insertMeterage.setTotal(detail.getTotal());
            insertMeterage.setRemainderAmount(detail.getAmount());
            insertMeterage.setAlreadyAmount(BigDecimal.ZERO);
            insertMeterage.setRemainderTotal(detail.getTotal());
            insertMeterage.setAlreadyTotal(BigDecimal.ZERO);
            insertMeterage.setComplete(Constants.NO);
            insertMeterage.setPlace(detail.getPlace());
            insertMeterage.setItem(detail.getItem());
            insertMeterage.setBeginStation(detail.getBeginStation());
            insertMeterage.setEndStation(detail.getEndStation());
            insertMeterage.setChangeOrderNo(master.getChangeOrderNo());
            insertMeterage.setCreateBy(master.getCreateBy());
            insertMeterage.setCreateTime(master.getCreateTime());
            changeMeterageList.add(insertMeterage);
        }
        meterageMapper.insertBatch(changeMeterageList);
    }

}
